#include "BlockQueue.hpp"
#include "Task.hpp"
#include <ctime>

void *Consumer(void *args){
    //BlockQueue<int> *bq = static_cast<BlockQueue<int> *>(args);
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);

    while(true){
        // 消费
        //sleep(2);
        // int data = bq->pop();
        // std::cout << "消费了一个数据：" << data << std::endl;


        // 从仓库中消费数据
        Task t = bq->pop();
        // 加工处理数据
        t.run();
        std::cout << "消费了一个任务：" << t.GetResult() << " thread: " << pthread_self() << std ::endl;
    }
}

void *Producter(void *args){
    //BlockQueue<int> *bq = static_cast<BlockQueue<int> *>(args);
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
    int data = 0;
    while (true)
    {
        // 生产
        // sleep(2);
        // data++;
        // bq->push(data);
        // std::cout << "生产了一个数据：" << data << std::endl;


        // 获取数据
        sleep(1);
        int data1 = rand() % 10 + 1;
        int data2 = rand() % 10;
        char op = opers[rand() % opers.size()];
        Task t(data1, data2, op);
        // 生产数据到仓库中
        bq->push(t);
        std::cout << "生产了一个任务：" << t.GetTask() << " thread: " << pthread_self() << std::endl;
    }
}

int main(){
    srand(time(nullptr));

    // 创建一个阻塞队列对象充当特定的内存
    // BlockQueue<int> *bq = new BlockQueue<int>();
    BlockQueue<Task> *bq = new BlockQueue<Task>();

    // // 创建两个线程--生产者和消费者
    // pthread_t c, p;
    // pthread_create(&c, nullptr, Consumer, bq);
    // pthread_create(&p, nullptr, Producter, bq);
    // // 等待回收两个线程
    // pthread_join(c, nullptr);
    // pthread_join(p, nullptr);

    // 创建多生产者线程和多消费者线程
    pthread_t c[3], p[5];
    for (int i = 0; i < 3; i++){
        pthread_create(c + i, nullptr, Consumer, bq);
        sleep(1);
    }
    for (int i = 0; i < 5; i++){
        pthread_create(p + i, nullptr, Producter, bq);
        sleep(1);
    }

    // 等待回收所有线程
    for (int i = 0; i < 3; i++){
        pthread_join(c[i], nullptr);
    }
    for (int i = 0; i < 5; i++){
        pthread_join(p[i], nullptr);
    }

    // 释放阻塞队列
    delete bq;

    return 0;
}